﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace block_explorer
{
    class PointLight : BaseSceneLight
    {
        public Vector3 Position;
        public float Range;

        private int mShadowMapSize;
        private RenderTargetCube mShadowMap;

        public PointLight()
        {
            Position = Vector3.Zero;
            Range = 1.0f;

            mShadowMapSize = 512;
        }

        public PointLight(Vector3 position, Color color, float range)
            :base(color)
        {
            Position = position;
            Range = range;

            mShadowMapSize = 512;
        }

        public override void PrepareShadowMap(GraphicsDevice device)
        {
            mShadowMap = new RenderTargetCube(device, mShadowMapSize, false, SurfaceFormat.Single, DepthFormat.Depth24);
        }

        public override void DrawShadowMap(GraphicsDevice device, Shaders.ShadowMapEffect occlusionEffect, Scene scene, SceneCamera camera)
        {
            float near = 0.1f;
            float far = Range;
            Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, 1.0f, near, far);

            Camera lightCamera = new Camera();
            lightCamera.Projection = projection;

            Matrix[] views = new Matrix[6];
            views[0] = Matrix.CreateLookAt(Position, Position + new Vector3(0, 0, -1), Vector3.Down);
            views[1] = Matrix.CreateLookAt(Position, Position + new Vector3(0, 0, 1), Vector3.Down);
            views[2] = Matrix.CreateLookAt(Position, Position + new Vector3(-1, 0, 0), Vector3.Down);
            views[3] = Matrix.CreateLookAt(Position, Position + new Vector3(1, 0, 0), Vector3.Down);
            views[4] = Matrix.CreateLookAt(Position, Position + new Vector3(0, -1, 0), Vector3.Backward);
            views[5] = Matrix.CreateLookAt(Position, Position + new Vector3(0, 1, 0), Vector3.Forward);

            occlusionEffect.Technique = Shaders.ShadowMapEffect.ShadowTechnique.Point;

            device.SetRenderTarget(mShadowMap, CubeMapFace.PositiveZ);
            device.Clear(Color.White);
            occlusionEffect.Passes[0].Apply();
            camera.View = views[0];
            scene.Draw(occlusionEffect, lightCamera);

            device.SetRenderTarget(mShadowMap, CubeMapFace.NegativeZ);
            device.Clear(Color.White);
            occlusionEffect.Passes[0].Apply();
            camera.View = views[1];
            scene.Draw(occlusionEffect, lightCamera);

            device.SetRenderTarget(mShadowMap, CubeMapFace.PositiveX);
            device.Clear(Color.White);
            occlusionEffect.Passes[0].Apply();
            camera.View = views[2];
            scene.Draw(occlusionEffect, lightCamera);

            device.SetRenderTarget(mShadowMap, CubeMapFace.NegativeX);
            device.Clear(Color.White);
            occlusionEffect.Passes[0].Apply();
            camera.View = views[3];
            scene.Draw(occlusionEffect, lightCamera);

            device.SetRenderTarget(mShadowMap, CubeMapFace.PositiveY);
            device.Clear(Color.White);
            occlusionEffect.Passes[0].Apply();
            camera.View = views[4];
            scene.Draw(occlusionEffect, lightCamera);

            device.SetRenderTarget(mShadowMap, CubeMapFace.NegativeY);
            device.Clear(Color.White);
            occlusionEffect.Passes[0].Apply();
            camera.View = views[5];
            scene.Draw(occlusionEffect, lightCamera);
        }

        public override Texture ShadowMap { get { return mShadowMap; } }
    }
}
